package v3.chapter3.notifyHoldLock; 

public class Run {

	public static void main(String[] args) {
		Object lock=new Object();
		ThreadA a=new ThreadA(lock);
		a.start();
		NotifyThread b=new NotifyThread(lock);
		b.start(); 
		synNotifyMethodThread c=new synNotifyMethodThread(lock);
		c.start();
	}

}


class ThreadA extends Thread{
	private Object lock;
	public ThreadA(Object lock) {
		super();
		this.lock=lock;
	}
	
	@Override
	public void run() {
		Service service=new Service();
		service.testMethod(lock);
	}
}

class NotifyThread extends Thread{
	private Object lock;
	public NotifyThread(Object lock) {
		super();
		this.lock=lock;
	}
	
	@Override
	public void run() {
		Service service=new Service();
		service.synNotifyMethod(lock);
	}
}

class synNotifyMethodThread extends Thread{
	private Object lock;
	public synNotifyMethodThread(Object lock) {
		super();
		this.lock=lock;
	}
	
	@Override
	public void run() {
		Service service=new Service();
		service.synNotifyMethod(lock);
	}
}

class Service{
	public void testMethod(Object lock) {
		try {
			synchronized(lock) {
				System.out.println("begin wait() ThreadName="+Thread.currentThread().getName());
			    lock.wait();
				System.out.println(" end wait() ThreadName="+Thread.currentThread().getName());
			}
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void synNotifyMethod(Object lock) {
		try {
			synchronized(lock) {
				System.out.println("begin notify() ThreadName="+Thread.currentThread().getName()+" time="+System.currentTimeMillis());
			    lock.notify();
			    Thread.sleep(5000);
				System.out.println(" end notify() ThreadName="+Thread.currentThread().getName()+" time="+System.currentTimeMillis());
			}
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}